package doing;

public class Monitor {
	private static final int MAX_LOAD=4;
	private int here;
	private int next;
	private int[] waitEntry = new int[7];
	private int[] waitExit = new int[7];
	private int load;
	private LiftView lift;
	
	public Monitor(LiftView v) {
		lift = v;
	}
	
	synchronized public void elevatorWait(int floor) {
		while (true) {
			boolean empty = load==0;
			for (int i: waitEntry) {
				empty = empty && i==0;
			}
			if (empty) {
				try {
					wait();
				} catch (InterruptedException e) {e.printStackTrace();}
			} else {
				break;
			}
		}
		
		while ((waitEntry[floor] != 0 && load != MAX_LOAD) || waitExit[floor] != 0) {
			try {
				wait();
			} catch (InterruptedException e) {e.printStackTrace();}
		}
	}
	
	synchronized public void setHere(int here) {
		this.here = here;
		lift.drawLift(here, load);
		notifyAll();
	}
	synchronized public int getHere() {
		return here;
	}
	public void setNext(int next) {
		synchronized (this) {
			this.next = next;
		}
		lift.moveLift(here, next);
	}
	
	synchronized public void waitForElevator(int entry, int exit) {
		lift.drawLevel(entry, ++waitEntry[entry]);
		notifyAll();
		while (here != next || here != entry || load >= MAX_LOAD) {
			try {
				this.wait();
			} catch (InterruptedException e) {e.printStackTrace();}
		}
		
		waitEntry[entry]--;
		load++;
		waitExit[exit]++;
		lift.drawLevel(entry, waitEntry[entry]);
		lift.drawLift(entry, load);
		notifyAll();
		waitForExit(exit);
	}

	private void waitForExit(int exit) {
		while (here != next || here != exit) {
			try {
				this.wait();
			} catch (InterruptedException e) {e.printStackTrace();}
		}
		
		load--;
		waitExit[exit]--;
		lift.drawLift(exit, load);
		notifyAll();
	}
}
